package com.zsk.shop.service;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zsk.shop.common.base.BaseResponse;
import com.zsk.shop.common.base.NoMsgException;
import com.zsk.shop.common.base.model.token.UserSimple;
import com.zsk.shop.common.constant.Constant;
import com.zsk.shop.common.constant.RedisKeys;
import com.zsk.shop.common.utils.*;
import com.zsk.shop.entity.GopMenu;
import com.zsk.shop.entity.GopRole;
import com.zsk.shop.entity.GopUser;
import com.zsk.shop.entity.TokenInfo;
import com.zsk.shop.enums.EnumUserType;
import com.zsk.shop.enums.ServiceKeyTypeEnum;
import com.zsk.shop.mapper.GopUserMapper;
import com.zsk.shop.model.params.GopUserAddParams;
import com.zsk.shop.model.params.GopUserEditParams;
import com.zsk.shop.model.params.GopUserLoginParams;
import com.zsk.shop.model.results.GopLoginInfoResult;
import com.zsk.shop.model.results.GopUserListResult;
import com.zsk.shop.model.results.GopUserLoginResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class GopUserService extends ServiceImpl<GopUserMapper, GopUser> {

    @Autowired
    private TokenInfoService tokenInfoService;

    @Autowired
    private TokenUtil tokenUtil;

    @Autowired
    private GopMenuService menuService;

    @Autowired
    private GopRoleService roleService;

    public BaseResponse<GopLoginInfoResult> login(GopUserLoginParams params) {
        String phone = params.getPhone();
        if (ToolUtil.isEmpty(phone)) {
            return BaseResponse.error("当前手机号为空");
        } else {
            if (phone.equals("admin")) {
            }
//            else if (RegexCheckUtils.isNotMobile(phone)) {
//                return BaseResponse.error("请填写正确格式的手机号码");
//            }
        }
        GopLoginInfoResult result = this.loginUser(params);
        if (ToolUtil.isNotEmpty(result.getToken())) {
            return BaseResponse.success(result);
        } else {
            return BaseResponse.error("当前账号信息不存在");
        }
    }

    private GopLoginInfoResult loginUser(GopUserLoginParams params) {
        GopLoginInfoResult loginInfoResult = new GopLoginInfoResult();
        loginInfoResult.setMenuUrl(new ArrayList<>());
        loginInfoResult.setToken("");
        GopUser user = this.queryTrueUserByPhone(params.getPhone());
        if (ToolUtil.isEmpty(user)) {
            return loginInfoResult;
        }
        //校验密码
        loginInfoResult.setGopUser(EntityConvertUtils.convertAToB(user, GopUserLoginResult.class));
        if (ToolUtil.isEmpty(user.getPwd()) || !user.getPwd().equals(params.getPwd())) {
            return loginInfoResult;
        }
        //查询用户之前的登录状态，如果已登录之前的掉线
        this.clearUserInfoByUserNo(user.getId());
        UserSimple userSimple = EntityConvertUtils.convertAToB(user, UserSimple.class);
        userSimple.setUserType(EnumUserType.USER.getCode());
        userSimple.setIsGop(true);
        loginInfoResult.setToken(tokenUtil.genToken(userSimple, null));
        //补全菜单
        if (user.getId().equals(0L)) {
            loginInfoResult.setMenuUrl(getAllMenuUrls());
        } else {
            Long roleId = user.getRoleId();
            if (ToolUtil.isEmpty(roleId)) {
                loginInfoResult.setMenuUrl(new ArrayList<>());
            } else {
                loginInfoResult.setMenuUrl(menuService.getMenuUrlByRoleId(roleId));
            }
        }
        return loginInfoResult;
    }

    private void clearUserInfoByUserNo(Long id) {
        //Token
        List<TokenInfo> tokenInfos = tokenInfoService.queryUnInvalidTokensByUserId(id, null, true);
        for (TokenInfo tokenInfo : tokenInfos) {
            RedisUtil.delete(RedisKeys.gopUser.getHashKey(tokenInfo.getToken()));
        }
        tokenInfoService.invalidTokens(tokenInfos);
    }

    private GopUser queryTrueUserByPhone(String phone) {
        LambdaQueryWrapper<GopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GopUser::getPhone, phone);
        queryWrapper.eq(GopUser::getIsDeleted, false);
        queryWrapper.eq(GopUser::getIsInvalid, false);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    public BaseResponse<GopLoginInfoResult> getMenuByRoleId() {
        GopLoginInfoResult gopLoginInfoResult = new GopLoginInfoResult();
        GopUser user = this.queryByUserNo(HttpContext.getUserNo());
        gopLoginInfoResult.setMenuUrl(new ArrayList<>());
        GopUserLoginResult gopUserLoginResult = EntityConvertUtils.convertAToB(user, GopUserLoginResult.class);
        gopUserLoginResult.setRoleName(roleService.queryByRoleId(gopUserLoginResult.getRoleId()));
        gopLoginInfoResult.setGopUser(gopUserLoginResult);
        if (ToolUtil.isEmpty(user)) {
            return BaseResponse.success(gopLoginInfoResult);
        }
        //特殊管理员
        if (user.getId().equals(0L)) {
            gopLoginInfoResult.setMenuUrl(getAllMenuUrls());
            return BaseResponse.success(gopLoginInfoResult);
        }
        gopLoginInfoResult.setMenuUrl(this.menuService.getMenuUrlByRoleId(user.getRoleId()));
        return BaseResponse.success(gopLoginInfoResult);
    }

    private List<String> getAllMenuUrls() {
        //EntityConvertUtils.str2list("*");
        return menuService.list().stream().map(GopMenu::getUrl).collect(Collectors.toList());
    }

    private GopUser queryByUserNo(String userNo) {
        LambdaQueryWrapper<GopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GopUser::getUserNo, userNo);
        queryWrapper.last("limit 1");
        return this.getOne(queryWrapper);
    }

    public BaseResponse setRoleId(Long userId, Long roleId) {
        LambdaUpdateWrapper<GopUser> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(GopUser::getRoleId, roleId);
        updateWrapper.set(GopUser::getUpdateTime, new Date());
        updateWrapper.set(GopUser::getUpdateUser, HttpContext.getUserId());
        updateWrapper.eq(GopUser::getId, userId);
        return BaseResponse.success(this.update(updateWrapper));
    }

    public BaseResponse addGopUser(GopUserAddParams params) {
        GopUser user = EntityConvertUtils.convertAToB(params, GopUser.class);
        String userNo = RedisUtil.getServiceKeyHaveDateByType(ServiceKeyTypeEnum.GOP_USER.getValue());
        user.setUserNo(userNo);
        user.setCreateUser(HttpContext.getUserId());
        user.setUpdateUser(HttpContext.getUserId());
        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());
        user.setIsDeleted(false);
        if (ToolUtil.isEmpty(user.getAvatar())) {
            user.setAvatar("https://oss.zhishangkeapp.com/icon/20210705172323.png");
        }
        this.save(user);
        return BaseResponse.success("新增管理员成功");
    }

    public BaseResponse updateGopUser(GopUserEditParams params) {
        if (ToolUtil.isOneEmpty(params, params.getId(), params.getName(), params.getPhone(), params.getGender())) {
            throw new NoMsgException(400, "参数不完整");
        }
        GopUser old = this.getById(params.getId());
        String avatar = old.getAvatar();
        if (ToolUtil.isEmpty(old)) {
            return BaseResponse.error("当前角色数据不存在");
        }
        BeanUtil.copyProperties(params, old);
        if (ToolUtil.isEmpty(params.getAvatar())) {
            old.setAvatar(avatar);
        }
        old.setUpdateUser(HttpContext.getUserId());
        old.setUpdateTime(new Date());
        return BaseResponse.success(this.updateById(old));
    }

    public BaseResponse gopUserList() {
        LambdaQueryWrapper<GopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(GopUser::getIsDeleted, false);
        queryWrapper.orderByDesc(GopUser::getUserNo);
        List<GopUser> gopUserList = this.list(queryWrapper);
        List<GopUserListResult> result = PageWithSqlUtil.getList(gopUserList, GopUserListResult.class);
        List<Long> roleIds = result.stream().map(GopUserListResult::getRoleId).collect(Collectors.toList());
        List<GopRole> gopRoleList = roleService.queryUnInValidByRoleIds(roleIds);
        for (GopUserListResult gopUserListResult : result) {
            gopUserListResult.setPwd("");
            if (gopUserListResult.getId().equals(Constant.GOP_ADMIN_USER_ID)) {
                gopUserListResult.setRoleName("超级管理员");
            }
            GopRole gopRole = gopRoleList.stream().filter(x -> x.getId().equals(gopUserListResult.getRoleId())).findFirst().orElse(new GopRole());
            gopUserListResult.setRoleName(gopRole.getName());
        }
        return BaseResponse.success("获取管理员用户列表成功", result, gopUserList.size());
    }

    public BaseResponse reviewGopUser(String gopUserId, Boolean invalid) {
        GopUser gopUser = this.getById(gopUserId);
        gopUser.setIsInvalid(invalid);
        gopUser.setUpdateTime(new Date());
        return BaseResponse.success(this.saveOrUpdate(gopUser));

    }

    public BaseResponse delGopUser(Long id) {
        LambdaUpdateWrapper<GopUser> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(GopUser::getIsDeleted, true);
        updateWrapper.eq(GopUser::getId, id);
        this.update(updateWrapper);
        return BaseResponse.success();
    }

    public BaseResponse updateGopUserPwd(String userNo, String pwd, String oldPwd) {
        //如果oldPwd存在则校验，如果为空则直接替换pwd
        GopUser user = this.queryByUserNo(userNo);
        if (ToolUtil.isNotEmpty(oldPwd)) {
            if (ToolUtil.isNotEmpty(pwd) && !user.getPwd().equals(oldPwd)) {
                return BaseResponse.error("老密码校验失败！");
            }
        }
        user.setPwd(pwd);
        this.saveOrUpdate(user);
        return BaseResponse.success("当前密码设置成功！");
    }

    public List<GopUser> queryNameByIds(List<Long> userIds) {
        if (ToolUtil.isEmpty(userIds)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<GopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(GopUser::getId, GopUser::getName);
        queryWrapper.in(GopUser::getId, userIds);
        return list(queryWrapper);
    }

    public List<GopUser> queryNameByNos(List<String> userNos) {
        if (ToolUtil.isEmpty(userNos)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<GopUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(GopUser::getUserNo, GopUser::getName);
        queryWrapper.in(GopUser::getUserNo, userNos);
        return list(queryWrapper);
    }
}
